import { ApiResult } from '../ApiResult/ApiResult';
import { httpUtil } from '../Http/HttpUtil';
import { RequestOptions } from '../Http/RequestOptions';
import { BusinessError } from '@kit.BasicServicesKit';

/**
 * 利用Map保存参数和值的映射关系  为避免参数名及方法名重复 采用组合Key的方法
 */
interface FunParamMapKey {
  target: Object; //所在类
  methodName: string; //所在方法
  index: number; //参数名索引值
}

let funParamMap = new Map<string, string>();

// @Get注解 拿到url 从函数的@Param拿到参数名及参数值 利用HttpUtil进行网络请求
export function Get(url: string) {
  return (target: object, methodName: string, descriptor: PropertyDescriptor) => {
    const originalMethod = descriptor.value;
    let URL: string = url;
    let options: RequestOptions = {
      url: URL,
      queryParams: {}
    };
    let myParam = ''
    descriptor.value = async (...args: any[]) => {
      //对于方法中的每一个（methodName，arg）遍历加入到网络请求配置中
      args.forEach((arg, index) => {
        // 通过已知的信息构造组合Key对象
        let obj: FunParamMapKey = { target: target, methodName: methodName, index: index };
        // 通过组合Key（通过对内容的比较而不是值 节省内存）从内存map中获取@Param修饰的内容
        let paramName = funParamMap[JSON.stringify(obj)];
        console.log("paramName:"+paramName)
        // 将正确的参数名及值添加至网络请求参数中
        if (typeof paramName !== 'undefined') {
          if (typeof arg === 'string' || typeof arg === 'object' || arg instanceof ArrayBuffer ||
            typeof arg === 'number') {
            options.queryParams[paramName] = arg;
          } else {
            console.log('参数类型不对');
            throw new Error(`Invalid parameter type at index ${index}.`);
          }
        }else {
          myParam = arg
          //如果获取不到形参名 及未被@Param标记 并且参数的类型是对象
          // if (typeof arg === 'object') {
          //   options.queryParams['timeId'] = arg;
          // }
          options.url = `${URL}?timeId=${myParam}`
        }
        console.log("arg:"+arg)
      });
      //拼接请求参数
      // const urlParams = Object.keys(options.queryParams).map(key => `${key}=${options.queryParams[key]}`).join('&');
      // console.log('urlParams:', urlParams);
      // if (URL.includes("?")) {
      //   options.url = `${URL}${urlParams}`;
      // } else {
      //   options.url = `${URL}?${urlParams}`;
      // }
      // console.log("------url:"+options.url)
      const p = new Promise<ApiResult<boolean>>((resolve, reject) => {
        httpUtil.Get(options).then((response) => {
          const result: ApiResult<boolean> = response;
          // console.log("---------"+response)
          resolve(result);
        }).catch((error: BusinessError) => {
          reject(error);
        });
      });
      return await p;
    };
  };
}

// @Post注解 拿到url 从函数的@Param拿到参数名及参数值 利用HttpUtil进行Post网络请求
export function Post(url: string) {
  return (target: object, methodName: string, descriptor: PropertyDescriptor) => {
    const originalMethod = descriptor.value;
    let options: RequestOptions = {
      url: url,
      extraData: {}
    };
    descriptor.value = async (...args: any[]) => {
      //对于方法中的每一个（methodName，arg）遍历加入到网络请求配置中
      args.forEach((arg, index) => {
        console.log("参数值", JSON.stringify(arg));
        // 通过已知的信息构造组合Key对象
        let obj: FunParamMapKey = { target: target, methodName: methodName, index: index };
        // 通过组合Key（通过对内容的比较而不是值 节省内存）从内存map中获取@Param修饰的内容
        let paramName = funParamMap[JSON.stringify(obj)];
        console.log("参数名：", paramName);
        // 将正确的参数名及值添加至网络请求参数中
        if (typeof paramName !== 'undefined') {
          if (typeof arg === 'string' || typeof arg === 'object' || arg instanceof ArrayBuffer) {
            options.extraData[paramName] = arg;
          } else {
            throw new Error(`Invalid parameter type at index ${index}.`);
          }
        } else {
          //如果获取不到形参名 及未被@Param标记 并且参数的类型是对象
          if (typeof arg === 'object') {
            options.extraData = JSON.stringify(arg);
          }
        }
      });
      console.log('extraData', JSON.stringify(options.extraData));
      const p = new Promise<ApiResult<boolean>>((resolve, reject) => {
        httpUtil.Post(options).then((response) => {
          const result: ApiResult<boolean> = response;
          resolve(result);
        }).catch((error) => {
          reject(error);
        });
      });
      return await p;
    };
  };
}
/**
 * @Param 注解将想要获取的Param添加至内存Map中
 * @param paramName
 * @returns
 */
export function Param(paramName: string) {
  return (target: object, methodName: string, parameterIndex: number) => {
    let obj: FunParamMapKey = { target: target, methodName: methodName, index: parameterIndex };
    funParamMap[JSON.stringify(obj)] = paramName;
  };
}






